package org.zfm.car.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.zfm.car.domain.CarType;
import org.zfm.car.mapper.CarTypeMapper;
import org.zfm.car.service.ICarTypeService;
import org.zfm.base.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.zfm.constants.BasicConstant;

import java.io.Serializable;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 * @author zara
 * @since 2022-11-03
 */
@Service
public class CarTypeServiceImpl extends BaseServiceImpl<CarType> implements ICarTypeService {

    @Autowired
    private CarTypeMapper carTypeMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public List<CarType> getTree(Long pid) {
        Object tree = redisTemplate.opsForValue().get(BasicConstant.RedisData.CAR_TYPE_TREE);
        //判断缓存中有没有数据
        if(Objects.nonNull(tree)) {
            //如果有数据，就直接返回
            return (List<CarType>)tree;
        }
        //加锁，防止热点数据过期，大量请求访问数据库
        synchronized (CarTypeServiceImpl.class){
            //在从缓存中获取一次，如果有，就直接将缓存中的数据返回
            tree = redisTemplate.opsForValue().get(BasicConstant.RedisData.CAR_TYPE_TREE);
            //判断缓存中有没有数据
            if(Objects.nonNull(tree)) {
                //如果有数据，就直接返回
                return (List<CarType>)tree;
            }
            //如果没有，就查询数据库，
            List<CarType> carTypeList = getCarTypeByLoop(pid);
            //如果数据库也没有数据，就将空数据加入缓存中,防止大量请求访问空数据 大量请求访问数据库
            if(Objects.isNull(carTypeList)){
                redisTemplate.opsForValue().set(BasicConstant.RedisData.CAR_TYPE_TREE,new ArrayList<>());
            }
            //添加到缓存中，然后返回
            redisTemplate.opsForValue().set(BasicConstant.RedisData.CAR_TYPE_TREE,carTypeList);
            return carTypeList;
        }
    }

    @Override
    public void insert(CarType carType) {
        super.insert(carType);
        //清空缓存
        redisTemplate.delete(BasicConstant.RedisData.CAR_TYPE_TREE);
    }

    @Override
    public void delete(Serializable id) {
        super.delete(id);
        //清空缓存
        redisTemplate.delete(BasicConstant.RedisData.CAR_TYPE_TREE);
    }

    @Override
    public void update(CarType carType) {
        super.update(carType);
        //清空缓存
        redisTemplate.delete(BasicConstant.RedisData.CAR_TYPE_TREE);
    }

    //循环方案一
    private List<CarType> getCarTypeByLoop(Long pid){
        List<CarType> tree = new ArrayList<>();
        List<CarType> carTypeList = carTypeMapper.selectAll();
        for (CarType carType : carTypeList) {
            if(carType.getPid().equals(pid)){
                tree.add(carType);
            }else {
                for (CarType type : carTypeList) {
                    if(carType.getPid().equals(type.getId())){
                        type.getChildren().add(carType);
                    }
                }
            }
        }
        return tree;
    }


    //循环方案二
    private List<CarType> getCarTypeByLoopWithMap(Long pid){
        List<CarType> tree = new ArrayList<>();
        List<CarType> carTypeList = carTypeMapper.selectAll();
        Map<Long,CarType> map = new HashMap<>();
        carTypeList.forEach(carType -> {
            map.put(carType.getId(),carType);
        });
        carTypeList.forEach(carType -> {
            if(carType.getPid().equals(pid)){
                tree.add(carType);
            }else {
                map.get(carType.getPid()).getChildren().add(carType);
            }
        });

        return tree;
    }

    /**
     * 递归实现无限级查询 -- 频繁操作数据库，数据库负载过大
     * @param pid
     * @return 返回查询好的树
     */
    private List<CarType> getCarTypes(Long pid) {
        List<CarType> carTypeList = carTypeMapper.selectByParentId(pid);
        if(carTypeList==null){
            return null;
        }
        for (CarType carType : carTypeList) {
            List<CarType> children = getCarTypes(carType.getId());
            carType.setChildren(children);
        }
        return carTypeList;
    }
}
